from typing import Optional
from uuid import UUID

from dependency_injector.wiring import Provide, inject
from fastapi import APIRouter, Depends, HTTPException

from fastapi_template.common.responses import CommonResp
from fastapi_template.containers import Container
from fastapi_template.domains.user import (UserCreateDTO, UserDTO, UserFacade,
                                           UserUpdateDTO)

router = APIRouter(prefix="/users", tags=["users"])


@router.post("", response_model=CommonResp[UserDTO])
@inject
async def create_user(
    user_data: UserCreateDTO,
    user_facade: UserFacade = Depends(Provide[Container.user_facade])
) -> CommonResp[UserDTO]:
    """Create a new user."""
    try:
        user = await user_facade.create_user(user_data)
        return CommonResp.ok(data=user)
    except Exception as e:
        return CommonResp.fail(msg=str(e))


@router.get("/{user_id}", response_model=CommonResp[Optional[UserDTO]])
@inject
async def get_user(
    user_id: UUID,
    user_facade: UserFacade = Depends(Provide[Container.user_facade])
) -> CommonResp[Optional[UserDTO]]:
    """Get user by ID."""
    user = await user_facade.get_user_by_id(user_id)
    if not user:
        raise HTTPException(status_code=404, detail="User not found")
    return CommonResp.ok(data=user)


@router.put("/{user_id}", response_model=CommonResp[Optional[UserDTO]])
@inject
async def update_user(
    user_id: UUID,
    user_data: UserUpdateDTO,
    user_facade: UserFacade = Depends(Provide[Container.user_facade])
) -> CommonResp[Optional[UserDTO]]:
    """Update user information."""
    user = await user_facade.update_user(user_id, user_data)
    if not user:
        raise HTTPException(status_code=404, detail="User not found")
    return CommonResp.ok(data=user)


@router.delete("/{user_id}", response_model=CommonResp[bool])
@inject
async def delete_user(
    user_id: UUID,
    user_facade: UserFacade = Depends(Provide[Container.user_facade])
) -> CommonResp[bool]:
    """Delete user by ID."""
    success = await user_facade.delete_user(user_id)
    if not success:
        raise HTTPException(status_code=404, detail="User not found")
    return CommonResp.ok(data=True)
